#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>

extern int errno;

typedef void (*sighandler_t)(int);
static char *my_argv[100], *my_envp[100];
static char *search_path[10];

void handle_signal(int signo)
{
	printf("\nmeow> ");
	fflush(stdout);
}

void fill_argv(char *tmp_argv)
{
	char *foo = tmp_argv;
	int index = 0;
	char ret[100];
	bzero(ret, 100);
	while(*foo != '\0') {
		if(index == 10)
			break;

		if(*foo == ' ') {
			if(my_argv[index] == NULL)
				my_argv[index] = (char *)malloc(sizeof(char) * strlen(ret) + 1);
			else {
				bzero(my_argv[index], strlen(my_argv[index]));
			}
			strncpy(my_argv[index], ret, strlen(ret));
			strncat(my_argv[index], "\0", 1);
			bzero(ret, 100);
			index++;
		} else {
			strncat(ret, foo, 1);
		}
		foo++;
		/*printf("foo is %c\n", *foo);*/
	}
	my_argv[index] = (char *)malloc(sizeof(char) * strlen(ret) + 1);
	strncpy(my_argv[index], ret, strlen(ret));
	strncat(my_argv[index], "\0", 1);
}

void copy_envp(char **envp)
{
	int index = 0;
	for(;envp[index] != NULL; index++) {
		my_envp[index] = (char *)malloc(sizeof(char) * (strlen(envp[index]) + 1));
		memcpy(my_envp[index], envp[index], strlen(envp[index]));
	}
}

void get_path_string(char **tmp_envp, char *bin_path)
{
	int count = 0;
	char *tmp;
	while(1) {
		tmp = strstr(tmp_envp[count], "PATH");
		if(tmp == NULL) {
			count++;
		} else {
			break;
		}
	}
	strncpy(bin_path, tmp, strlen(tmp));
}

void insert_path_str_to_search(char *path_str)
{
	int index=0;
	char *tmp = path_str;
	char ret[100];

	while(*tmp != '=')
		tmp++;
	tmp++;

	while(*tmp != '\0') {
		if(*tmp == ':') {
			strncat(ret, "/", 1);
			search_path[index] = (char *) malloc(sizeof(char) * (strlen(ret) + 1));
			strncat(search_path[index], ret, strlen(ret));
			strncat(search_path[index], "\0", 1);
			index++;
			bzero(ret, 100);
		} else {
			strncat(ret, tmp, 1);
		}
		tmp++;
	}
}

int attach_path(char *cmd)
{
	//wtf is ret?
	char ret[100];
	int index;
	int fd;
	bzero(ret, 100);
	for(index=0;search_path[index]!=NULL;index++) {
		strcpy(ret, search_path[index]);
		strncat(ret, cmd, strlen(cmd));
		printf("%s\n", search_path[index]);
		if((fd = open(ret, O_RDONLY)) > 0) {
			strncpy(cmd, ret, strlen(ret));
			close(fd);
			return 0;
		}
	}
	return 0;
}

void call_execve(char *cmd)
{
	int i;
	printf("cmd is %s\n", cmd);
	if(fork() == 0) {
		i = execve(cmd, my_argv, my_envp);
		printf("errno is %d\n", errno);
		if(i < 0) {
			printf("%s: %s\n", cmd, "command not found");
			exit(1);
		}
	} else {
		wait(NULL);
	}
}

void free_argv()
{
	int index;
	for(index=0;my_argv[index]!=NULL;index++) {
		bzero(my_argv[index], strlen(my_argv[index])+1);
		my_argv[index] = NULL;
		free(my_argv[index]);
	}
}

//parses for dynamic path entry
char* parse_new_path(char *new_path){
	char *temp, *temp_str;
	temp = (char *)malloc(strlen(new_path));

	strcat(temp, "/");
	strtok(new_path, "/");
	new_path = strtok(NULL, "\n");

	strcat(temp, new_path);

	return temp;

}

void set_path(char* new_path){

	char* temp_path = (char*)malloc(sizeof(char)*100);
	char* leftover = (char*)malloc(sizeof(char)*20);

	char* temp = (char*)malloc(sizeof(char)*20);
	int index = 0;

	new_path = parse_new_path(new_path);

	//printf("the whole path is: %s\n", new_path);

	temp = strtok(new_path, ":\n");

	search_path[index] = (char*)malloc(sizeof(char) * strlen(temp));
	strncat(search_path[index], temp, strlen(temp));
	strncat(search_path[index], "/\0",2);

	while(temp != NULL){
		index++;
		temp = strtok(NULL, ":\n");
		if(temp == NULL)
			break;
		search_path[index] = (char*)malloc(sizeof(char) * strlen(temp));
		strncat(search_path[index], temp, strlen(temp));
		strncat(search_path[index], "/\0",2);
		//printf("token: %s\n", temp);
	}
}

//executes the command
void execute(char *tmp, char *cmd){
	//insert switch statement to catch additional symbols like & and |
	int fd;
	fill_argv(tmp);
	strncpy(cmd, my_argv[0], strlen(my_argv[0]));
	strncat(cmd, "\0", 1);
	if(index(cmd, '/') == NULL) {
		if(attach_path(cmd) == 0) {
			call_execve(cmd);
		} else {
			printf("%s: command not found\n", cmd);
		}
	} else {
		if((fd = open(cmd, O_RDONLY)) > 0) {
			close(fd);
			call_execve(cmd);
		} else {
			printf("%s: command not found\n", cmd);
		}
	}
	free_argv();
	printf("meow> ");
	bzero(cmd, 100);
}

void import_config(char* config_path, char* path_ret, char* data_ret){

	char* temp = (char*)malloc(sizeof(char)*100);

	FILE* fhandle;	//file handle

	fhandle = fopen(config_path, "r");
	if (fhandle == NULL)
		perror ("Error opening file");
	else {
		while(!feof(fhandle)){
			fgets (temp , 100 , fhandle);
			if(strstr(temp, "PATH"))
				strcpy(path_ret, temp);
			if(strstr(temp, "DATA"))
				strcpy(data_ret, temp);
		}
		fclose (fhandle);
	}
	free(temp);
}
//TODO LIST

int main(int argc, char *argv[], char *envp[])
{
	//variable declarations
	char c;
	int i;//, fd;
	char *tmp = (char *)malloc(sizeof(char) * 100);
	char *path_str = (char *)malloc(sizeof(char) * 256);
	char *data_str = (char *)malloc(sizeof(char) * 256);
	char *cmd = (char *)malloc(sizeof(char) * 100);

	//path to config file
	char *config_path = "./config.sh142";

	signal(SIGINT, SIG_IGN);
	signal(SIGINT, handle_signal);


	import_config(config_path, path_str, data_str);
	set_path(path_str);

	//copies environment variables into my_envp(global variable)
	//copy_envp(envp);
	//creates path to bin
	//get_path_string(my_envp, path_str);
	//not sure yet, searches if path exists?
	//insert_path_str_to_search(path_str);


	for(i=0;i<10;i++){
		printf("%s\n", search_path[i]);
	}
	//return 0;

	if(fork() == 0) {
		//execve("/usr/bin/clear", argv, my_envp);
		exit(1);
	} else {
		wait(NULL);
	}
	printf("meow> ");
	fflush(stdout);

	//bloody brilliant string input
	while(c != EOF) {
		c = getchar();
		switch(c) {
			case '\n':
			if(tmp[0] == '\0') {
				printf("meow> ");
			}
			else if(strstr(tmp, "PATH")){
				set_path(tmp);
				printf("meow> ");
				//return 0;
			}
			else if(strstr(tmp, "DATA")){
					//parse for data
				return 0;
			}
			else {
					//basically you can run this function anywhere as long it is within the scope or the while loop
				execute(tmp, cmd);
			}
			bzero(tmp, 100);
			break;
			default: strncat(tmp, &c, 1);
			break;
		}
	}
	free(tmp);
	free(path_str);
	for(i=0;my_envp[i]!=NULL;i++)
		free(my_envp[i]);
	for(i=0;i<10;i++)
		free(search_path[i]);
	printf("\n");
	return 0;
}
